package cn.hg.solon.youcan.framework.web.pear;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.dromara.hutool.core.convert.ConvertUtil;
import org.dromara.hutool.core.reflect.FieldUtil;
import org.dromara.hutool.core.text.CharSequenceUtil;
import org.dromara.hutool.core.util.ObjUtil;

import cn.hg.solon.youcan.common.vo.BaseVo;
import cn.hg.solon.youcan.framework.web.pear.LayuiTree.LayuiTreeSelectItem;

/**
 * Layui Tree树组件结果对象
 * <p>
 * https://layui.dev/docs/2.8/tree/
 * </p>
 *
 * @author 胡高
 */
public class LayuiTree<T extends Serializable> extends BaseVo implements Iterable<LayuiTreeSelectItem<T>> {

    /**
     * 树状选择项VO
     *
     * @author 胡高
     * @date 2021/12/20
     */
    public static class LayuiTreeSelectItem<T> extends BaseVo {

        /**
         * serialVersionUID
         */
        private static final long serialVersionUID = 3131301585276339948L;

        /**
         * ID
         */
        private Object id;

        /**
         * 父ID
         */
        private Object parentId;

        /**
         * 标题
         */
        private String title;

        /**
         * 节点是否初始展开
         */
        private boolean spread = true;

        /**
         * 节点是否初始为选中状态
         */
        private boolean checked = false;
        
        /**
         * 节点是否为禁用状态
         */
        private boolean disabled = false;

        /**
         * 子项列表
         */
        private List<LayuiTreeSelectItem<T>> children = new ArrayList<>();

        public LayuiTreeSelectItem(T bean, String idField, String parentIdField, String titleField,
            String checkedField) {
            this.id = FieldUtil.getFieldValue(bean, idField);
            this.parentId = FieldUtil.getFieldValue(bean, parentIdField);
            this.title = ConvertUtil.toStr(FieldUtil.getFieldValue(bean, titleField));
            Object checkVal = FieldUtil.getFieldValue(bean, checkedField);

            if (ObjUtil.isNotNull(checkVal)) {
                this.checked = ConvertUtil.toBoolean(checkVal);
            }
        }

        /**
         * @return the children
         */
        public List<LayuiTreeSelectItem<T>> getChildren() {
            return this.children;
        }

        /**
         * @return the id
         */
        public Object getId() {
            return this.id;
        }

        /**
         * @return the parentId
         */
        public Object getParentId() {
            return this.parentId;
        }

        /**
         * @return the name
         */
        public String getTitle() {
            return this.title;
        }

        public boolean isChecked() {
            return this.checked;
        }

        /**
         * @return the disabled
         */
        public boolean isDisabled() {
            return this.disabled;
        }

        public boolean isSpread() {
            return this.spread;
        }

        public void setChecked(boolean checked) {
            this.checked = checked;
        }

        /**
         * @param children the children to set
         */
        protected void setChildren(List<LayuiTreeSelectItem<T>> children) {
            this.children = children;
        }

        public void setSpread(boolean spread) {
            this.spread = spread;
        }

    }

    /**
     * serialVersionUID
     */
    private static final long serialVersionUID = 3562904133537565003L;

    /**
     * 树对象数组
     */
    private List<LayuiTreeSelectItem<T>> data;

    /**
     * 通过ID字段名、上级ID字段名、标题字段名、初始顶层ID值创建树对象
     *
     * @param beanList      bean对象列表
     * @param idField       ID字段名
     * @param parentIdField 上级字段名
     * @param titleField    标题字段名
     * @param parentIdValue 初始顶层ID值
     */
    public LayuiTree(List<T> beanList, String idField, String parentIdField, String titleField, String checkedField, Object parentIdValue) {
        this(beanList, idField, parentIdField, titleField, checkedField, parentIdValue, null);
    }

    /**
     * 通过ID字段名、上级ID字段名、标题字段名、初始顶层ID值创建树对象
     *
     * @param beanList      bean对象列表
     * @param idField       ID字段名
     * @param parentIdField 上级字段名
     * @param titleField    标题字段名
     * @param parentIdValue 初始顶层ID值
     * @param spreadLayer   展开层次
     */
    public LayuiTree(List<T> beanList, String idField, String parentIdField, String titleField, String checkedField, Object parentIdValue,
        Integer spreadLayer) {

        // 转换项目列表为树状选择项列表
        List<LayuiTreeSelectItem<T>> itemList = this.convertToItemList(beanList, CharSequenceUtil.toCamelCase(idField),
            CharSequenceUtil.toCamelCase(parentIdField), CharSequenceUtil.toCamelCase(titleField),
            CharSequenceUtil.toCamelCase(checkedField),
            parentIdValue);

        // 构建树状对象
        this.data = this.buildTree(itemList, parentIdValue, spreadLayer, 1);
    }

    public void add(int index, LayuiTreeSelectItem<T> element) {
        this.data.add(index, element);
    }

    private List<LayuiTreeSelectItem<T>> buildTree(final List<LayuiTreeSelectItem<T>> beanList, Object parentId,
        Integer spreadLayer, int layer) {
        List<LayuiTreeSelectItem<T>> data = new ArrayList<>();

        for (LayuiTreeSelectItem<T> item : beanList) {

            if (ObjUtil.equals(parentId, item.getParentId())) {
                if (ObjUtil.isNotNull(spreadLayer) && spreadLayer.intValue() < layer) {
                    item.setSpread(false);
                }

                data.add(item);
            }

        }

        for (LayuiTreeSelectItem<T> item : data) {
            item.setChildren(this.buildTree(beanList, item.getId(), spreadLayer, layer + 1));
        }

        return data;
    }

    private List<LayuiTreeSelectItem<T>> convertToItemList(List<T> list, String idName, String parentIdName,
        String nameField, String checkedField, Object initParentId) {
        List<LayuiTreeSelectItem<T>> itemList = new ArrayList<>();
        for (T bean : list) {
            itemList.add(new LayuiTreeSelectItem<>(bean, idName, parentIdName, nameField, checkedField));
        }

        return itemList;
    }

    @Override
    public Iterator<LayuiTreeSelectItem<T>> iterator() {
        return this.data.iterator();
    }
}
